package com.ww.springboot.boot.algorithm.stack;

import cn.hutool.core.util.ObjectUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 接雨水
 * --添加图形化  --将栈进出画出来
 * <p>
 * pop :出栈
 * peek :取栈顶元素
 *
 * @author wanwei
 * @since 2021-04-17 17:03
 */
public class TrapSwingWithStackDemo2 extends JFrame {

    private static int[] array = {};

    private static int RADIUS = 20;

    private static List<String> list = new ArrayList<>();

    private static int total = 0;

    private static Long sleep = 1L;

    private static Long info_sleep = 1L;

    /**
     * 下一个值
     */
    private static String nextNum = "";

    /**
     * 当前坐标
     */
    private static int indexNum = 0;

    /**
     * 提示2
     */
    private static String info2 = "";

    private static int start = 0;

    private static int end = 0;

    private static StackSelf<Integer> stackSelf = new StackSelf<>();

    public TrapSwingWithStackDemo2(int[] array1) {
        add(new Composition());

        array = array1;
    }

    public static void main(String[] args) throws InterruptedException {

        int[] array5 = {6, 4, 2, 0, 3, 2, 0, 3, 1, 4, 5, 3, 2, 7, 5, 3, 0, 1, 2, 1, 3, 4, 6, 8, 1, 3};

        JFrame frame = new TrapSwingWithStackDemo2(array5);
        frame.setTitle("积雨图");
        frame.setSize(830, 600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        new Thread(() -> {
            try {
                method(array5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    private static void method(int[] height) throws InterruptedException {
        int max = 0;
        for (int i = 0; i < height.length; i++) {
            if (max < height[i]) {
                max = height[i];
            }
        }


        StackSelf<Integer> index = new StackSelf<>();
        int nextNumMax = 0;
        //1.遍历
        for (int i = 0; i < height.length; i++) {
            //重置
            start = 0;
            end = 0;
            info2 = "";

            indexNum = i;
            //将数字入栈
            int num = height[i];
            nextNum = String.valueOf(num);
            if (stackSelf.empty() || num < stackSelf.peek()) {
                stackSelf.push(num);
                index.push(i);
            } else {
                //碰到高的柱子 开始
                //取出栈顶元素
                while (!stackSelf.empty()) {
                    if (stackSelf.peek() == 0) {
                        stackSelf.pop();
                        index.pop();
                        continue;
                    }
                    if (num >= stackSelf.peek()) {
                        int oldNum = stackSelf.peek();
                        start = i;
                        end = index.peek();
                        info2(num + "->" + oldNum + "开始存水");
                        int pop = stackSelf.pop();
                        int indexValue = index.pop();

                        if (i - indexValue - 1 > 0 && (pop - nextNumMax) > 0) {
                            //添加【储水空间】
                            total += (i - indexValue - 1) * (pop - nextNumMax);
                            list.add(i + "*" + indexValue + "*" + pop + "*" + nextNumMax);
                            TimeUnit.SECONDS.sleep(sleep);
                        }
                        if (nextNumMax < pop) {
                            nextNumMax = pop;
                        }
                    } else {
                        start = i;
                        end = index.peek();
                        info2(num + "->" + stackSelf.peek() + "开始存水");
                        stackSelf.peek();
                        int indexValue = index.peek();
                        if (i - indexValue - 1 > 0 && (num - nextNumMax) > 0) {
                            //添加【储水空间】
                            total += (i - indexValue - 1) * (num - nextNumMax);
                            list.add(i + "*" + indexValue + "*" + num + "*" + nextNumMax);
                            TimeUnit.SECONDS.sleep(sleep);
                        }
                        break;
                    }
                }
                //栈空时，清空上一个栈值
                nextNumMax = 0;
                stackSelf.push(num);
                index.push(i);
            }
        }
        System.out.println("-------------------总空间为：" + total + "----------");
    }

    private static void info2(String text) throws InterruptedException {
        info2 = text;
        TimeUnit.SECONDS.sleep(info_sleep);
    }

    static class Composition extends JPanel {

        public Composition() {
            Timer timer = new Timer(100, new Refresh());
            timer.start();
        }


        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //栈图
            stackSelf.paint(g);

            Font fontDefault = g.getFont();
            Color colorDefault = g.getColor();
            //画树状图
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array[i]; j++) {
                    if (start != 0 && i == start) {
                        g.setColor(Color.blue);
                    }
                    if (end != 0 && i == end) {
                        g.setColor(Color.blue);
                    }
                    g.drawRect(10 + RADIUS * i, 200 - RADIUS * j, RADIUS, RADIUS);
                    g.setColor(colorDefault);
                }
            }

            //画坐标
            for (int i = 0; i < array.length; i++) {
                if (indexNum == i) {
                    g.setColor(Color.blue);
                }
                g.drawString(String.valueOf(i), 10 + RADIUS * i + 5, 240);
                g.setColor(colorDefault);
            }
            //画积雨
            g.setFont(fontDefault);
            g.setColor(Color.red);
            for (String s : list) {
                String[] array = s.split("\\*");
                int xEnd = Integer.parseInt(array[0]);
                int xStart = Integer.parseInt(array[1]);

                int yEnd = Integer.parseInt(array[2]);
                int yStart = Integer.parseInt(array[3]);

                for (int x = xStart + 1; x < xEnd; x++) {
                    for (int y = yStart; y < yEnd; y++) {
                        g.drawRect(10 + RADIUS * x, 200 - RADIUS * y, RADIUS, RADIUS);
                    }
                }
            }

            g.setColor(Color.red);
            g.setFont(new Font(null, Font.BOLD, 20));
            if (ObjectUtil.isNotEmpty(info2)) {
                //提示2
                g.setColor(Color.red);
                g.setFont(new Font(null, Font.BOLD, 30));
                g.drawString("高度：" + info2, 200, 300);
                g.drawString("坐标：" + start + "->" + end + "开始存水", 200, 350);
            }


            g.setColor(Color.blue);
            g.setFont(new Font(null, Font.BOLD, 20));
            g.drawString("当前高度：" + nextNum, 200, 50);
            g.drawString("当前积水：" + total, 350, 50);
        }

        class Refresh implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                //重画
                repaint();
            }
        }

    }
}
